﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using GTServices.Entities;
using Caliburn.Micro;
using GTServices.WPF.Client.Controls;
using GTServices.Model;
using System.Windows.Data;
using GTServices.WPF.Client.Interfaces;
using GTServices.WPF.Client.Extensions;
using System.Windows;
using System.Windows.Controls;

namespace GTServices.WPF.Client.ViewModels.Entities
{
    public class CategoryViewModel : PropertyChangedBase, ISelectable, IEntityViewModel
    {

        public String Name
        {
            get { return Category.Name; }
            set
            {
                Category.Name = value;
                NotifyOfPropertyChange(() => Name); 
            }
        }
        public String Description
        {
            get { return Category.Description; }
            set
            {
                Category.Description = value;
                NotifyOfPropertyChange(() => Description);
            }
        }
        public String ExploitScenario
        {
            get { return Category.ExploitScenario; }
            set
            {
                Category.ExploitScenario = value;
                NotifyOfPropertyChange(() => ExploitScenario);
            }
        }
        public String Recommendation
        {
            get { return Category.Recommendation; }
            set
            {
                Category.Recommendation = value;
                NotifyOfPropertyChange(() => Recommendation);
            }
        }
        public String References
        {
            get { return Category.References; }
            set
            {
                Category.References = value;
                NotifyOfPropertyChange(() => References);
            }
        }

        public bool Moderated
        {
            get { return Category.Moderated; }
            set
            {
                Category.Moderated = value;
                NotifyOfPropertyChange(() => Moderated);
            }
        }
        public bool IsPublic
        {
            get { return Category.IsPublic; }
            set
            {
                Category.IsPublic = value;
                NotifyOfPropertyChange(() => IsPublic);
            }
        }
        public int Severity
        {
            get { return Category.Severity; }
            set
            {
                Category.Severity = value;
                NotifyOfPropertyChange(() => Severity);
            }
        }

        private bool _isSelected;
        public bool IsSelected
        {
            get { return _isSelected; }
            set
            {
                _isSelected = value;
                SelectionStateChanged(value); 
                NotifyOfPropertyChange(() => IsSelected);
            }
        }

        public Classification Classification
        {
            get { return Category.Classification; }
            set
            {
                Category.Classification = value;
                NotifyOfPropertyChange(() => Classification);
            }
        }


        public Template Template
        {
            get { return Category.Template; }
            set
            {
                Category.Template = value;
                NotifyOfPropertyChange(() => Template);
            }
        }
        private Category _Category;
        public Category Category { 
            get { return _Category; } 
            set { 
                _Category = value;
               
                NotifyOfPropertyChange(() => Patterns);
                NotifyOfPropertyChange(() => Category);          
            } 
        }


        public PatternViewModel SelectedPatternViewModel { get; set; }

        public List<PatternViewModel> SelectedPatternViewModels { get; set; } 
        public ListCollectionView Patterns {
            get
            {
                var lcv = new ListCollectionView(ModelViewModels.Instance.PatternViewModels);
                lcv.Filter += new Predicate<object>(x => {
                    PatternViewModel pvm = x as PatternViewModel;
                    if (pvm != null && pvm.Pattern != null && Category.Patterns.Contains(pvm.Pattern))
                        return true;

                    return false;
                });
                lcv.SortDescriptions.Add(new System.ComponentModel.SortDescription("Pattern.PatternStr", System.ComponentModel.ListSortDirection.Ascending));
                return lcv;
            }
        }
        public object Model
        {
            get { return this.Category; }
            set
            {
                if (value is Category)
                    Category = value as Category;
            }
        }
        public CategoryViewModel()
        {
            SelectedPatternViewModels = new List<PatternViewModel>(); 
        }
        public void SelectionStateChanged(bool value)
        {
            var selectedLanguages = ModelViewModels.Instance.LanguageViewModels.Where(x => x.IsSelected); 
            //Select the related patterns
            foreach (PatternViewModel pvm in this.Patterns)
            {
                if (value == false)
                {
                    //Deselecting 
                    var otherPatternsSelected = ModelViewModels.Instance.CategoryViewModels.Where(x => x.IsSelected && x != this).SelectMany(x=>x.Category.Patterns);

                    if (!otherPatternsSelected.Contains(pvm.Pattern))
                    {
                        pvm.IsSelected = false;
                    }
                }
                else
                {
                    var lvm = ModelViewModels.Instance.LanguageViewModels.FirstOrDefault(x => x.Name == "All File Types"); 
                    if( selectedLanguages.Count() == 0 || 
                        selectedLanguages.FirstOrDefault( x=> pvm.Language == x.Language) != null || 
                        (pvm.Language != null && pvm.Language.Name == "All") || 
                        lvm != null
                        )
                            pvm.IsSelected = true;
                }
            }
        }

        public void AddPattern()
        {
            List<PatternViewModel> pvms = new List<PatternViewModel>(); 
            foreach(PatternViewModel pvm in this.Patterns){
                pvms.Add(pvm);
            }
            //Get all the patterns not associated with another Category. 
            var patternVMS = ModelViewModels.Instance.PatternViewModels.Except(pvms);
            
            //Going to need to add a way to filter. 
            PatternListPickerViewModel lpvm = new PatternListPickerViewModel(patternVMS.ToList());
         
            if (GTWindowManager.Instance.ShowDialog(lpvm, 300, 300) == true && lpvm.SelectedItems != null && lpvm.SelectedItems.Count > 0)
            {
                lpvm.SelectedItems.ForEach((x) =>
                {
                    PatternViewModel pvm = x as PatternViewModel;
                    pvm.Pattern.Categories.Add(this.Category);
                    this.Category.Patterns.Add(pvm.Pattern);
                    pvm.NotifyOfPropertyChange(() => pvm.FirstCategoryIfExists); 
                });
                NotifyOfPropertyChange(() => Patterns); 
            }
        }
        public void SelectTemplate()
        {
            var templates = ModelViewModels.Instance.TemplateViewModels.ToList();

            ListPickerViewModel lpvm = new ListPickerViewModel(templates.ToList<Object>(), "Template.Name", "Template.Name");


            if (GTWindowManager.Instance.ShowDialog(lpvm, 300, 300) == true && lpvm.SelectedItem != null)
            {
                this.Template = (lpvm.SelectedItem as TemplateViewModel).Template;
            }
        }

        public void SelectClassification()
        {
            var templates = ModelViewModels.Instance.ClassficationViewModels.ToList();

            ListPickerViewModel lpvm = new ListPickerViewModel(templates.ToList<Object>(), "Classification.Name", "Classification.Name");


            if (GTWindowManager.Instance.ShowDialog(lpvm, 300, 300) == true && lpvm.SelectedItem != null)
            {
                this.Classification = (lpvm.SelectedItem as ClassificationViewModel).Classification;
            }
        }

        public void RemovePatterns()
        {
            if (this.SelectedPatternViewModels != null && this.SelectedPatternViewModels.Count() > 0)
            {
                foreach (PatternViewModel pvm in this.SelectedPatternViewModels.ToList())
                {
                    Category.Patterns.Remove(pvm.Pattern);
                    pvm.Pattern.Categories.Remove(Category);
                    pvm.NotifyOfPropertyChange(() => pvm.FirstCategoryIfExists);
                    
                }
                NotifyOfPropertyChange(() => Patterns);
            }
        }

        public void SelectedPatternItemChanged(ActionExecutionContext context)
        {
            SelectionChangedEventArgs eventArgs = context.EventArgs as SelectionChangedEventArgs;
            ListView lv = context.Source as ListView;
            if (lv != null)
            {
                this.SelectedPatternViewModels.Clear();

                foreach (PatternViewModel pvm in lv.SelectedItems)
                {
                    this.SelectedPatternViewModels.Add(pvm);
                }
            }
            NotifyOfPropertyChange(() => SelectedPatternViewModels);
        }
    }
}
